@Thread t1 = new Thread( )で Threadクラスのオブジェクトを作成する。 ・コンストラクタのパラメータにThreadStartクラスのオブジェクトを指定 ・ThreadStartクラスのコンストラクタには、デリゲートInvokeメソッドを指定する Aデリゲートを宣言する B実際に実行するメソッドを作成する CデリゲートInvokeメソッドでデリゲートに実際に実行するメソッドを実装する 上記の4項目がスレッド生成・生成スレッドからの書込みをする場合必要となる 下記のプログラムは以下の仕様である。 @ button1をクリックすると起動スレッドからlabel1に現在時刻を書き込む A button2をクリックすると生成した別スレッドからlabel1に現在時刻を書き込む |
実行結果 | |
<プログラム例> using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace WindowsFormsmultithread { public partial class Form1 : Form { public Form1() { InitializeComponent(); } //デリゲート宣言する delegate void MyDelegate(); void DisplayTime() { //現在の時刻を表示する label1.Text = DateTime.Now.ToString(); } void DisplayTime2() { label1.Text = DateTime.Now.ToString(); } public void myInvoke() //デリゲートInvokeメソッド { //Invokeが必要な時はInvokeを使い、不必要の時は直接書き込む if (InvokeRequired) Invoke(new MyDelegate(DisplayTime2)); //デリゲートにメソッドを実装 else DisplayTime(); } private void button1_Click(object sender, EventArgs e) //Form1スレッドから表示 { myInvoke(); } private void button2_Click(object sender, EventArgs e) //第2スレッドから表示 { Thread t1 = new Thread(new ThreadStart(myInvoke));//Threadクラスのインスタンスを作成する //★ コンストラクタのパラメータにThreadStartクラスのオブジェクトを指定する。 //★ ThreadStartクラスのコンストラクタには、デリゲートInvokeメソッドを指定する t1.Start(); //スレッド実行 } } } |
@BackgroundWorkerコンポーネントをフォームにドラッグする AackgroundWorker1.RunWorkerAsync( )メソッドでバックグランドワーカの別スレッドを起動させる。 BbackgroundWorker1_DoWork( ) イベントハンドラで別スレッドからのレポートを受ける CBackgroundWorker1_RunWorkerCompleted( )イベントハンドラで別スレッドの処理終了レポートを受ける Dキャンセルが発生していないか別スレッドで定期的にチェックする。キャンセルの発生有無はBackgroundWorker1_RunWorkerCompleted( )イベントハンドラで 常時チェックする |
実行結果 | |
using System; |
<起動時> <バックグランドスレッド動作中> <バックグランスレッド処理 正常終了後> <キャンセル発生後> |
■ 別スレッドから フォーム上のコントロールを操作(ランプ フリーラン)
マルチスレッド制御には、いくつかあるようですが 単に2〜3個の別スレッドから速度をあまり問題とせずメインフォームのコントロールを 操作するだけならINVOKEでデリゲートを呼び出す方法が一番簡単です。 Win32APIのセフォマやミューテックス関数を使った排他制御は結構大変です。 どのように排他制御、メモリ保護が行われているかといったことは不問にして マイクロソフトが用意してくれたデリゲート(意味:代表、代理人)にINVOKE (意味:祈願する、お願いする)するのが賢明です。 使い方はいたって簡単です。 @デリゲートの型を宣言する delegate (戻り値) (デリゲート型名)(引数1,引数2,.........); (例) delegate void MyDelegate(bool flag,); A呼び出す関数を定義する。 → この関数の中に 実際に操作したいフォームのコントロールのメソッドを書くことができる。 private void ContFunc(bool flag) //関数を定義 { ... . .. } B別スレッドメソッドの中に デリゲートのインスタンスを生成し、呼び出し関数も含め定義する。 MyDelegate mydelegate = new MyDelegate(ContFunc); C関数をINVOKEメソッドで呼び出す this.Invoke(mydelegate, Flag); //関数の呼び出し 以下は、バックグラウンドワーカの別スレッドから メインフレームのラベルとピクチャーボックスを操作しています。 backgroundWorker1_DoWork( )の 中は while(true)でエンドレスになっています。 スリープ1秒 x 2個を繰り返して デリゲートによりラベルとピクチャーボックスを1秒ごとに書き換えています。 |
|
using System; |
|
<実行結果> | |
<ランプ オフの場合> <ランプ オンの場合> |